package com.cskaoyan.wordmemorize.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cskaoyan.wordmemorize.converter.ReviewConverter;
import com.cskaoyan.wordmemorize.dao.entity.UserCheckinStatisticsDO;
import com.cskaoyan.wordmemorize.dao.entity.UserRevStatisticsDO;
import com.cskaoyan.wordmemorize.dao.entity.UserVocBoundStatisticsDO;
import com.cskaoyan.wordmemorize.dao.entity.UserVocRevDO;
import com.cskaoyan.wordmemorize.dao.mapper.UserCheckinStatisticsMapper;
import com.cskaoyan.wordmemorize.dao.mapper.UserRevStatisticsMapper;
import com.cskaoyan.wordmemorize.dao.mapper.UserVocBoundStatisticsMapper;
import com.cskaoyan.wordmemorize.dao.mapper.UserVocRevMapper;
import com.cskaoyan.wordmemorize.dto.admin.PageDTO;
import com.cskaoyan.wordmemorize.dto.app.DownLoadUserReviewDTO;
import com.cskaoyan.wordmemorize.dto.app.UserReviewStatisticsDTO;
import com.cskaoyan.wordmemorize.dto.app.UserVocRevDTO;
import com.cskaoyan.wordmemorize.request.PageRequest;
import com.cskaoyan.wordmemorize.request.UserReviewDataCommand;
import com.cskaoyan.wordmemorize.service.UserReviewService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserReviewServiceImpl implements UserReviewService {
    @Autowired
    UserVocRevMapper userReviewMapper;
    @Autowired
    UserRevStatisticsMapper userRevStatisticsMapper;
    @Autowired
    ReviewConverter reviewConverter;
    @Autowired
    UserCheckinStatisticsMapper userCheckinStatisticsMapper;

    @Override
    public void synchronizeUserReviewData(UserReviewDataCommand command, Long userId) {
        //先不考虑卸载后再记忆新单词时前端之前数据清空
        //每次添加新单词前端会返回当天之前的学习记录要判重
        
        //先转换revStatisticsCommand并插入user_rev_statistics表
        UserRevStatisticsDO userRevStatisticsDO = reviewConverter.userRevStatisticsCommand2DO(command.getRevStatisticsCommand());
        //前端传的用户id不要使用
        //此时用户id一定一样，一定能找到这个用户，此时时间是唯一索引
        //可能用户登录时前端请求拿到之前的数据是用户id，之后根据这个返回
        userRevStatisticsDO.setUserId(userId);
        LambdaQueryWrapper<UserRevStatisticsDO> userRevStatisticsQueryWrapper = new LambdaQueryWrapper<>();
        userRevStatisticsQueryWrapper.eq(UserRevStatisticsDO::getUserId, userId)
                //找到当天的学习情况记录
                .eq(UserRevStatisticsDO::getReviewDate,userRevStatisticsDO.getReviewDate());
        //判断记录是否存在
        UserRevStatisticsDO isExist = userRevStatisticsMapper.selectOne(userRevStatisticsQueryWrapper);
        if(isExist==null){
            userRevStatisticsMapper.insert(userRevStatisticsDO);
        }else{
            LambdaUpdateWrapper<UserRevStatisticsDO> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(UserRevStatisticsDO::getUserId, userId)
                    .eq(UserRevStatisticsDO::getReviewDate,userRevStatisticsDO.getReviewDate());
            userRevStatisticsMapper.update(userRevStatisticsDO,updateWrapper);
        }

        //转换vocRevCommands并插入user_voc_rev表 前端会返回当天之前的学习单词记录判重
        List<UserVocRevDO> userVocRevDOS = reviewConverter.userVocRevCommands2DOs(command.getVocRevCommands());
        userVocRevDOS.forEach(userVocRevDO -> {
            //判重
            //同上此时用户id一定一样 单词id是唯一索引
            userVocRevDO.setUserId(userId);
            LambdaQueryWrapper<UserVocRevDO> vocQueryWrapper = new LambdaQueryWrapper<>();
            vocQueryWrapper.eq(UserVocRevDO::getUserId, userId)
                    .eq(UserVocRevDO::getVocId,userVocRevDO.getVocId());
            UserVocRevDO vocIsExist = userReviewMapper.selectOne(vocQueryWrapper);
            LambdaUpdateWrapper<UserVocRevDO> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(UserVocRevDO::getUserId, userId)
                    .eq(UserVocRevDO::getVocId,userVocRevDO.getVocId());
            if(vocIsExist==null){
                userReviewMapper.insert(userVocRevDO);
            }else {
                userReviewMapper.update(userVocRevDO,updateWrapper);
            }
        });

        //根据当天的学习时长更新用户的总学习时长 假定该表中用户数据已经存在
        LambdaUpdateWrapper<UserCheckinStatisticsDO> userUpdateWrapper = new LambdaUpdateWrapper<>();
        userUpdateWrapper.eq(UserCheckinStatisticsDO::getUserId,userId)
                .setSql("total_time=total_time+"+userRevStatisticsDO.getStudyTime());
        userCheckinStatisticsMapper.update(null,userUpdateWrapper);
    }

    @Override
    public DownLoadUserReviewDTO downloadUserReviewData(PageRequest pageRequest, Long userId) {
        //不会传keyword
        //得到userReviewStatisticsPage
        Page<UserRevStatisticsDO> pageParam = new Page<>(pageRequest.getPageNum(), pageRequest.getCount());
        LambdaQueryWrapper<UserRevStatisticsDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserRevStatisticsDO::getUserId,userId);
        Page<UserRevStatisticsDO> userRevStatisticsPage = userRevStatisticsMapper.selectPage(pageParam, queryWrapper);
        PageDTO<UserReviewStatisticsDTO> userReviewStatisticsDTO = reviewConverter.userRevStatistcsPage2PageDTO(userRevStatisticsPage.getRecords(),userRevStatisticsPage.getTotal());

        //得到userVocRevPage
        Page<UserVocRevDO> pageParam2 = new Page<>(pageRequest.getPageNum(), pageRequest.getCount());
        LambdaQueryWrapper<UserVocRevDO> vocQueryWrapper = new LambdaQueryWrapper<>();
        vocQueryWrapper.eq(UserVocRevDO::getUserId,userId);
        Page<UserVocRevDO> userVocRevPage = userReviewMapper.selectPage(pageParam2,vocQueryWrapper);
        PageDTO<UserVocRevDTO> userVocRevDTO = reviewConverter.userVocRevPage2PageDTO(userVocRevPage.getRecords(),userVocRevPage.getTotal());

        DownLoadUserReviewDTO downLoadUserReviewDTO = new DownLoadUserReviewDTO();
        downLoadUserReviewDTO.setUserVocRevPage(userVocRevDTO);
        downLoadUserReviewDTO.setUserReviewStatisticsPage(userReviewStatisticsDTO);
        return downLoadUserReviewDTO;
    }

    @Autowired
    UserVocBoundStatisticsMapper userVocBoundStatisticsMapper;
    @Override
    public void addUserRovRev(List<Long> vocIds, Long userId) {
        vocIds.forEach(vocId -> {
            UserVocRevDO userVocRevDO = new UserVocRevDO();
            userVocRevDO.setUserId(userId);
            userVocRevDO.setVocId(vocId);
            userVocRevDO.setType(0);
            //判重
            LambdaQueryWrapper<UserVocRevDO> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(UserVocRevDO::getUserId,userId)
                    .eq(UserVocRevDO::getVocId,vocId);
            UserVocRevDO isExist = userReviewMapper.selectOne(queryWrapper);
            if(isExist==null){
                userReviewMapper.insert(userVocRevDO);
                LambdaUpdateWrapper<UserVocBoundStatisticsDO> BoundWrapper = new LambdaUpdateWrapper<>();
                BoundWrapper.eq(UserVocBoundStatisticsDO::getUserId,userId)
                        .setSql("occupied=occupied+1")
                        .setSql("available=available-1");
                userVocBoundStatisticsMapper.update(null,BoundWrapper);
            }
            //已选过的单词也不update了
        });
    }
}
